// gpio_driver.c
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/gpio.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/uaccess.h>

#define DEVICE_NAME "gpio_device"
#define GPIO_PIN_1 17 // GPIO 引脚 1
#define GPIO_PIN_2 27 // GPIO 引脚 2
#define GPIO_PIN_3 22 // GPIO 引脚 3

static int major_number;

// 打开设备
static int gpio_open(struct inode *inode, struct file *file) {
    printk(KERN_INFO "GPIO device opened\n");
    return 0;
}

// 读取 GPIO 引脚的值
static ssize_t gpio_read(struct file *file, char __user *user_buffer, size_t count, loff_t *offset) {
    int value;
    char buf[2]; // 0 或 1

    // 读取 GPIO_PIN_1 的值
    value = gpio_get_value(GPIO_PIN_1);
    buf[0] = value + '0'; // 转换为字符
    buf[1] = '\0'; // 字符串结束符

    if (copy_to_user(user_buffer, buf, sizeof(buf))) {
        return -EFAULT; // 发生错误
    }

    printk(KERN_INFO "Read GPIO_PIN_1 value: %d\n", value);
    return sizeof(buf); // 返回读取的字节数
}

// 写入 GPIO 引脚的值
static ssize_t gpio_write(struct file *file, const char __user *user_buffer, size_t count, loff_t *offset) {
    char buf[2];

    if (copy_from_user(buf, user_buffer, sizeof(buf))) {
        return -EFAULT; // 发生错误
    }

    // 设置 GPIO_PIN_2 的值
    if (buf[0] == '1') {
        gpio_set_value(GPIO_PIN_2, 1); // 设置为高电平
    } else {
        gpio_set_value(GPIO_PIN_2, 0); // 设置为低电平
    }

    printk(KERN_INFO "Wrote %c to GPIO_PIN_2\n", buf[0]);
    return sizeof(buf); // 返回写入的字节数
}

// 关闭设备
static int gpio_close(struct inode *inode, struct file *file) {
    printk(KERN_INFO "GPIO device closed\n");
    return 0;
}

// 文件操作结构体
static struct file_operations fops = {
    .owner = THIS_MODULE,
    .open = gpio_open,
    .read = gpio_read,
    .write = gpio_write,
    .release = gpio_close,
};

// 初始化模块
static int __init gpio_driver_init(void) {
    major_number = register_chrdev(0, DEVICE_NAME, &fops);
    if (major_number < 0) {
        printk(KERN_ALERT "Failed to register GPIO device\n");
        return major_number;
    }

    // 请求 GPIO 引脚
    gpio_request(GPIO_PIN_1, "GPIO_PIN_1");
    gpio_request(GPIO_PIN_2, "GPIO_PIN_2");
    gpio_request(GPIO_PIN_3, "GPIO_PIN_3");

    // 设置 GPIO 引脚方向
    gpio_direction_input(GPIO_PIN_1); // GPIO_PIN_1 为输入
    gpio_direction_output(GPIO_PIN_2, 0); // GPIO_PIN_2 为输出，初始为低电平
    gpio_direction_output(GPIO_PIN_3, 0); // GPIO_PIN_3 为输出，初始为低电平

    printk(KERN_INFO "GPIO driver initialized with major number %d\n", major_number);
    return 0;
}

// 卸载模块
static void __exit gpio_driver_exit(void) {
    gpio_set_value(GPIO_PIN_2, 0); // 确保 GPIO_PIN_2 关闭
    gpio_free(GPIO_PIN_1); // 释放 GPIO 引脚
    gpio_free(GPIO_PIN_2);
    gpio_free(GPIO_PIN_3);
    unregister_chrdev(major_number, DEVICE_NAME); // 注销字符设备
    printk(KERN_INFO "GPIO driver unregistered\n");
}

module_init(gpio_driver_init);
module_exit(gpio_driver_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Your Name");
MODULE_DESCRIPTION("A simple GPIO driver for multiple pins");


/*

基于 Linux 的 GPIO 驱动，能够控制多个 GPIO 引脚的输入和输出，并实现基本的读写操作，可以按照以下步骤进行。下面是一个简单的 GPIO 驱动程序示例，支持多个 GPIO 引脚的控制
make
sudo insmod gpio_driver.ko

sudo mknod /dev/gpio_device c 240 0
cat /dev/gpio_device

echo 1 > /dev/gpio_device  # 设置 GPIO_PIN_2 为高电平
echo 0 > /dev/gpio_device  # 设置 GPIO_PIN_2 为低电平

*/